package models

/*
 +----------------------------------------------------------------------
 + Title        : 基础模型
 + Author       : huwl
 + Version      : 1.0.0
 + Initial-Time : 2018-01-06
 + Last-time    : 这个文件最后修改的时间 + 修改人的名称
 + Desc         : 基础模型
 +----------------------------------------------------------------------
*/

import (
	"common-service/tools"
)

// GORM插件
type Base struct{}

/**
 * 新增数据,支持批量
 * @param interface{} params ---------------------------------必传
 * @return int64, error
 */
func (model Base) Add(params interface{}) (int64, error) {
	tx := tools.DatabaseManager.Create(params)
	return tx.RowsAffected, tx.Error
}

/**
 * 分批批量新增
 * @param interface{} params ---------------------------------必传
 * @param int count ------------------------------------------必传
 * @return int64, error
 */
func (model Base) BatchAdd(params interface{}, count int) (int64, error) {
	tx := tools.DatabaseManager.CreateInBatches(params, count)
	return tx.RowsAffected, tx.Error
}

/**
 * 根据主键删除,支持批量10、[]int{1,2,3}
 * @param interface{} modelInstance --------------------------必传
 * @param interface{} primaryKey -----------------------------必传
 * @return int64, error
 */
func (model Base) DeleteByPrimaryKey(modelInstance, primaryKey interface{}) (int64, error) {
	tx := tools.DatabaseManager.Delete(modelInstance, primaryKey)
	return tx.RowsAffected, tx.Error
}

/**
 * 根据条件删除
 * @param interface{} modelInstance --------------------------必传
 * @param map[string]interface{} params ----------------------必传
 * @return int64, error
 */
func (model Base) DeleteByParams(modelInstance interface{}, params map[string]interface{}) (int64, error) {
	dbManager := tools.DatabaseManager.Model(modelInstance)
	for key, value := range params {
		dbManager.Where(key, value)
	}

	tx := dbManager.Delete(modelInstance)
	return tx.RowsAffected, tx.Error
}

/**
 * 根据条件更新数据
 * 根据 `struct` 更新属性，只会更新非零值的字段
 *	db.Model(&user).Where().Updates(User{Name: "hello", Age: 18, Active: false})
 *	UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;
 *
 *	根据 `map` 更新属性
 *	db.Model(&user).Where().Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
 *	UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
 *	params:map[string]interface{}{"name": "hello", "age": 18}
 *	wheres:"id IN ?", []int{10, 11}
 * @param interface{} modelInstance --------------------------必传
 * @param interface{} params ---------------------------------必传
 * @param map[string]interface{} wheres ----------------------必传
 * @return int64, error
 */
func (model Base) EditByParams(modelInstance, params interface{}, wheres map[string]interface{}) (int64, error) {
	dbManager := tools.DatabaseManager.Model(modelInstance)
	for key, value := range wheres {
		dbManager.Where(key, value)
	}

	tx := dbManager.Updates(params)
	return tx.RowsAffected, tx.Error
}

/**
 * 根据主键更新数据
 *	根据 `struct` 更新属性，只会更新非零值的字段
 *	db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
 *	UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;
 *
 *	根据 `map` 更新属性
 *	db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
 *	UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
 * @param interface{} modelInstance --------------------------必传
 * @param map[string]interface{} params ----------------------必传
 * @return int64, error
 */
func (model Base) EditByPrimaryKey(modelInstance, params, primaryKeyValue interface{}, primaryKeyName ...string) (int64, error) {
	primaryKey := "id"
	if len(primaryKeyName) > 0 {
		primaryKey = primaryKeyName[0]
	}
	tx := tools.DatabaseManager.Model(modelInstance).Where(primaryKey, primaryKeyValue).Updates(params)
	return tx.RowsAffected, tx.Error
}

/**
 * 根据主键获取信息
 * db.First(&user, "id = ?", "string_primary_key") modelInstance=&user
 *
 * @param interface{} modelInstance --------------------------必传
 * @param interface{} primaryKeyValue ------------------------必传
 * @param string primaryKeyName ------------------------------非必传
 * @return int64, error
 */
func (model Base) GetResultByPrimaryKey(modelInstance, primaryKeyValue interface{}, primaryKeyName ...string) (int64, error) {
	primaryKey := "id"
	if len(primaryKeyName) > 0 {
		primaryKey = primaryKeyName[0]
	}
	tx := tools.DatabaseManager.First(modelInstance, primaryKey, primaryKeyValue)
	if tx.Error != nil && tx.Error.Error() == "record not found" {
		return tx.RowsAffected, nil
	}
	return tx.RowsAffected, tx.Error
}

/**
 * 单条数据
 * db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
 * Where("name <> ?", "jinzhu")
 * Where("name IN ?", []string{"jinzhu", "jinzhu 2"})
 * Where("name LIKE ?", "%jin%")
 * Where("name = ? AND age >= ?", "jinzhu", "22")
 * Where("updated_at > ?", lastWeek)
 * Where("created_at BETWEEN ? AND ?", lastWeek, today)
 *
 * @param interface{} modelInstance --------------------------必传
 * @param interface{} result ---------------------------------必传
 * @param map[string]interface{} params ----------------------非必传
 * @return int64, error
 */
func (model Base) Row(modelInstance, result interface{}, params map[string]interface{}) (int64, error) {
	dbManager := tools.DatabaseManager.Model(modelInstance)
	for key, value := range params {
		dbManager.Where(key, value)
	}

	tx := dbManager.First(result)
	if tx.Error != nil && tx.Error.Error() == "record not found" {
		return tx.RowsAffected, nil
	}

	return tx.RowsAffected, tx.Error
}

/**
 * 根据多个主键获取多条数据
 *
 * @param interface{} modelInstance --------------------------必传
 * @param interface{} ids ------------------------------------必传
 * @param string field ---------------------------------------非必传
 * @return error
 */
func (model Base) Rows(modelInstance interface{}, ids []interface{}, field ...string) error {
	fieldName := "id"
	if len(field) > 0 {
		fieldName = field[0]
	}
	tx := tools.DatabaseManager.Where(fieldName+" IN ?", ids).Find(modelInstance)
	return tx.Error
}

/**
 * 根据条件获取信息
 *
 * @param interface{} modelInstance --------------------------必传，模型实例
 * @param interface{} result ---------------------------------必传，返回结果
 * @param map[string]interface{} params ----------------------必传，查询条件
 * @param int page -------------------------------------------必传，当前页
 * @param int pageSize ---------------------------------------必传,条数
 * @param string order ---------------------------------------必传，"age desc, name"支持多个
 * @return error
 */
func (model Base) GetResultsByParams(modelInstance, result interface{}, params map[string]interface{}, page, pageSize int, order string) error {
	dbManager := tools.DatabaseManager.Model(modelInstance)
	for key, value := range params {
		dbManager.Where(key, value)
	}

	if pageSize > 0 {
		tx := dbManager.Limit(pageSize).Offset((page - 1) * pageSize).Order(order).Find(result)
		return tx.Error
	}

	tx := dbManager.Order(order).Find(result)
	return tx.Error
}

/**
 * 根据条件获取数量
 *
 * @param interface{} modelInstance --------------------------必传，模型实例
 * @param *int64 count ---------------------------------------必传，返回结果
 * @param map[string]interface{} params ----------------------必传，查询条件
 * @return error
 */
func (model Base) GetTotalByParams(modelInstance interface{}, count *int64, params map[string]interface{}) error {
	dbManager := tools.DatabaseManager.Model(modelInstance)
	for key, value := range params {
		dbManager.Where(key, value)
	}
	tx := dbManager.Count(count)
	return tx.Error
}
